package hxy.dragon.ktor.service

import hxy.dragon.ktor.data.BaseResponse
import hxy.dragon.ktor.model.Colleague
import hxy.dragon.ktor.model.Colleagues
import hxy.dragon.ktor.model.ExposedColleagues
import kotlinx.coroutines.Dispatchers
import org.jetbrains.exposed.v1.core.ResultRow
import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.core.StdOutSqlLogger
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.like
import org.jetbrains.exposed.v1.jdbc.insert
import org.jetbrains.exposed.v1.jdbc.selectAll
import org.jetbrains.exposed.v1.jdbc.transactions.experimental.newSuspendedTransaction

//@Suppress("DEPRECATION")
suspend fun <T> dbQuery(block: suspend () -> T): T =
    newSuspendedTransaction(Dispatchers.IO) {
        addLogger(StdOutSqlLogger)
        block()
    }

/**
 * @description
 * @author HOX4SGH
 * @date 2024/7/13
 */
object ColleagueService {


    suspend fun listColleague(): List<ExposedColleagues> {
        return dbQuery {
            Colleague.all().map {
                ExposedColleagues(
                    id = it.id.value,
                    name = it.name,
                    age = it.age,
                    telephone = it.telephone
                )
            }
        }
    }

    suspend fun findColleague(colleague: ExposedColleagues): List<ExposedColleagues> {
        return dbQuery {
            Colleague.find {
                Colleagues.name like "%${colleague.name}%"
            }.map(::toExposedColleagues)
        }
    }

    @Deprecated(message = "直接是序列化不了的")
    suspend fun listAreas2(): List<Colleague> {
        return dbQuery {
            Colleague.all().toList() // 这里免去了绑定。但是ktor不支持，序列化不了
        }
    }

    suspend fun create(colleague: ExposedColleagues): BaseResponse = dbQuery {

        // 检查电话是否已经存在了
        val existingColleague = Colleague.find { Colleagues.telephone eq colleague.telephone.toString() }.firstOrNull()
        if (existingColleague != null) {
            return@dbQuery BaseResponse(409, "插入失败：电话已存在", data = "电话号码: ${colleague.telephone}")
//            return@dbQuery BaseResponse(409, "插入失败：电话已存在", "电话号码: ${colleague.telephone}")
        }
        try {
            val newColleague = Colleague.new {
                name = colleague.name
                age = colleague.age
                telephone = colleague.telephone.toString()
            }
            BaseResponse(200, "插入成功", newColleague.id.value)
        } catch (e: Exception) {
            // TODO   log.error("插入失败: ${e.message}")
            BaseResponse(500, "插入失败", data = e.message)
        }
    }

    suspend fun selectById(id: Int): ExposedColleagues? = dbQuery {
        Colleague.findById(id)?.let {
            ExposedColleagues(it.id.value, it.name, it.age)
        }
    }

    /**
     * 很像mybatis-plus的Model操作，删除必须先查询到，才能删除，感觉很费劲。sql都有操作两次，没啥必要性
     */
    suspend fun deleteColleague(id: Int): Boolean = dbQuery {
        val findById = Colleague.findById(id)
        if (findById != null) {
            findById?.delete()
            true
        } else {
            false
        }
    }

    suspend fun updateColleague(colleague: ExposedColleagues): ExposedColleagues? = dbQuery {
        colleague.id?.let { it ->
            Colleague.findByIdAndUpdate(it) {
                it.name = colleague.name
                it.age = colleague.age
            }?.let {
                ExposedColleagues(
                    id = it.id.value,
                    name = it.name,
                    age = it.age,
                )
            }
        }
    }

    /**
     *  DSL 查询
     */
    suspend fun createDSL(colleague: ExposedColleagues): Int = dbQuery {
        Colleagues.insert {
            it[name] = colleague.name
            it[age] = colleague.age
        }[Colleagues.id].value
    }

    suspend fun listColleaguesDSL(): List<ExposedColleagues> {
        var likeValue = "eric"
        return dbQuery {
            Colleagues.selectAll()
                .where { Colleagues.name like "%${likeValue}%" }
                .orderBy(Colleagues.id, SortOrder.DESC)
                .map(::resultToExposedColleagues)
//                .map { row ->
//                    ExposedColleagues(
//                        id = row[Colleagues.id].value,
//                        name = row[Colleagues.name],
//                        age = row[Colleagues.age]
//                    )
//                }
        }
    }

//    suspend fun deleteDSL(id: Int): Boolean? {
//        val deleteWhere = Colleagues.deleteWhere {
//            (Colleagues.id eq EntityID(id, Colleagues))
//        }
//        return deleteWhere > 0
//    }

//    suspend fun exceSQL(){
//        exec("""
//
//        """.trimIndent())
//    }

    fun toExposedColleagues(colleague: Colleague): ExposedColleagues = ExposedColleagues(
        colleague.id.value,
        colleague.name,
        colleague.age,
        colleague.telephone
    )

    fun resultToExposedColleagues(result: ResultRow): ExposedColleagues = ExposedColleagues(
        result[Colleagues.id].value,
        result[Colleagues.name],
        result[Colleagues.age],
        result[Colleagues.telephone]
    )

}